﻿//********************************************************************
// 
//  file:  frmExplorer.cs
// 
//  (C) Copyright 2010, Diomede Corporation
//  All rights reserved
// 
//  Use, modification, and distribution is subject to   
//  the New BSD License (See accompanying file license.txt).
// 
//********************************************************************

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Diomede.SDK;
using Microsoft.Win32;
using data.diomedestorage.com;

namespace Diomede.Explorer
{
    public partial class frmExplorer : Form
    {
        ISession session;
        PageInfo pageInfo;
        string lastclick = "";

        FileManager fileManager;

        public frmExplorer()
        {
            InitializeComponent();
            session = new Session();
            setControls(false);
            tsBtnLogin.Text = "Login";
            fileManager = new FileManager() { Session = session };
        }

        private void tsBtnLogin_Click(object sender, EventArgs e)
        {
            if (tsBtnLogin.Text == "Login")
            {
                using (frmLogin frm = new frmLogin())
                {
                    frm.StartPosition = FormStartPosition.CenterParent;
                    if (frm.ShowDialog(this) == DialogResult.OK)
                    {
                        if (string.IsNullOrEmpty(frm.UserName) || string.IsNullOrEmpty(frm.Password))
                        {
                            MessageBox.Show(this, "UserName or Password is invalid.", "Login error.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return;
                        }
                        if (!string.IsNullOrEmpty(frm.ServiceUrl))
                        {
                            session = new Session(true, frm.ServiceUrl, frm.TransferUrl);
                            writeStatus(string.Format("Logging in to {0}...",frm.ServiceUrl));
                        }
                        else
                            writeStatus("Logging in to Diomede Service...");

                        // save..
                        if (frm.Save)
                        {
                            RegistryKey rk = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Diomede Storage\\Diomede Explorer");
                            rk.SetValue("user", StringManip.EncodeTo64(frm.UserName));
                            rk.SetValue("pass", StringManip.EncodeTo64(frm.Password));
                            rk.Close();
                        }
                        else
                        {
                            RegistryKey rk = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Diomede Storage\\Diomede Explorer");
                            if (rk.GetValue("user") != null) rk.DeleteValue("user");
                            if (rk.GetValue("pass") != null) rk.DeleteValue("pass");
                            rk.Close();
                        }

                        this.Cursor = Cursors.WaitCursor;
                        ISessionExecResult result = session.Login(frm.UserName, frm.Password);
                        if (result.Status == Diomede.SDK.Enums.ExecutionResults.Success)
                        {
                            fileManager.Session = session;
                            writeStatus("Login successful.");
                            this.Text = string.Format("Exploring {0}'s files", frm.UserName);
                            tsBtnLogin.Text = "Logout";
                            tsBtnLogin.Image = Diomede.Explorer.Properties.Resources.logout.ToBitmap();
                            setControls(true);
                            LoadFolders(null);
                            tvFolders.Focus();
                        }
                        else
                        {
                            writeStatus(string.Format("Failed to login. - {0}", result.Message));
                            tsBtnLogin_Click(this, e);
                        }
                        this.Cursor = Cursors.Arrow;
                    }
                }
            }
            else
            {
                session.Logout();
                setControls(false);
                this.Text = "Diomede Service Explorer";
                writeStatus("Logout successful.");
                tsBtnLogin.Text = "Login";
                tsBtnLogin.Image = Diomede.Explorer.Properties.Resources.user.ToBitmap();
            }
        }

        void setControls(bool isLogin)
        {
            if (isLogin)
            {
                splitContainerMain.Panel1.Enabled = true;
                toolStripPaging.Enabled = true;
                toolStripButtonRefresh.Enabled = true;
                toolStripButtonUpload.Enabled = true;
                chkShowDeleted.Enabled = true;
                chkIncompleteFiles.Enabled = true;
                btnFilesSummary.Enabled = true;
                btnUserInfo.Enabled = true;
                btnMyEmails.Enabled = true;
                btnChangePassword.Enabled = true;
                btnDeleteAccount.Enabled = true;
                btnUploadActivityLogs.Enabled = true;
                btnDownloadActivityLog.Enabled = true;
                btnMyContracts.Enabled = true;
                btnMyProducts.Enabled = true;
                btnLoginActivityLogs.Enabled = true;
                btnInvoiceActivityLogs.Enabled = true;

            }
            else
            {
                splitContainerMain.Panel1.Enabled = false;
                toolStripPaging.Enabled = false;
                toolStripButtonRefresh.Enabled = false;
                toolStripButtonUpload.Enabled = false;
                chkShowDeleted.Enabled = false;
                chkIncompleteFiles.Enabled = false;
                btnFilesSummary.Enabled = false;
                btnUserInfo.Enabled = false;
                btnMyEmails.Enabled = false;
                btnChangePassword.Enabled = false;
                btnDeleteAccount.Enabled = false;
                btnUploadActivityLogs.Enabled = false;
                btnDownloadActivityLog.Enabled = false;
                btnMyContracts.Enabled = false;
                btnMyProducts.Enabled = false;
                btnLoginActivityLogs.Enabled = false;
                btnInvoiceActivityLogs.Enabled = false;

                lvFiles.Items.Clear();
            }
        }

        void writeStatus(string s)
        {
            this.tsLblStatus.Text = s;
            this.toolStripMain.Refresh();
        }

        private void btnShowFiles_Click(object sender, EventArgs e)
        {
            searchFiles("", null, null, 0, long.Parse((string)cboTxtSize.SelectedItem));
        }

        void searchFiles(string q, string metaName, string metaValue , long offset, long size)
        {
            writeStatus("Retrieving user files..");
            IFileManagement f = session as IFileManagement;
            bool? includeDeleted = false;
            if(chkShowDeleted.Checked) includeDeleted = null;
            bool? completeOnly = true;
            if (chkIncompleteFiles.Checked) completeOnly = null;

            IFileManagementExecResult result = f.SearchFiles(null, q, "", "", null, null, null, null,includeDeleted ,completeOnly, metaName, metaValue, offset, size);
            if (result.Status == Diomede.SDK.Enums.ExecutionResults.Success)
            {
                pageInfo = new PageInfo(result.TotalResultCount, offset, (int)size);
                writeStatus("");
                displayFiles(result.StoredFiles);
            }
            else
            {
                writeStatus(string.Format("Error retrieving files: {0}", result.Message));
            }
        }
        
        void displayFiles(List<IStoredFile> files)
        {
            lvFiles.Items.Clear();
            lvFiles.Columns.Clear();
            lvFiles.Columns.Add("FileName");
            lvFiles.Columns.Add("FileID");
            lvFiles.Columns.Add("Size");
            lvFiles.Columns.Add("Deleted");
            lvFiles.Columns.Add("IsComplete");

            foreach (var item in files)
            {
                ListViewItem i = lvFiles.Items.Add(item.FileId.Value.ToString(), item.FileInformation.fileName, 0);
                i.SubItems.Add(item.FileId.Value.ToString());
                i.SubItems.Add(item.FileInformation.fileSize.ToString());
                i.SubItems.Add(item.FileInformation.isDeleted.ToString());
                i.SubItems.Add(item.FileInformation.isComplete.ToString());
            }

            lvFiles.View = View.Details;
            lvFiles.Columns[0].Width = 400;
            lvFiles.Columns[1].Width = 100;
            lvFiles.Columns[2].Width = 100;
            lvFiles.Columns[3].Width = 100;
            lvFiles.Columns[4].Width = 100;

            lblTotalDisplay.Text = string.Format("{0} file(s) found.", pageInfo.TotalResults);
            lblPageDisplay.Text = string.Format("{0} of {1}", pageInfo.CurrentPage, pageInfo.TotalPage);
            if (pageInfo.NextOffset >= pageInfo.TotalResults)
            {
                btnNext.Enabled = false;
            }
            else
            {
                btnNext.Enabled = true;
            }
            if (pageInfo.PreviousOffset < 0)
            {
                btnPrev.Enabled = false;
            }
            else
            {
                btnPrev.Enabled = true;
            }
        }

        private void btnUploadFiles_Click(object sender, EventArgs e)
        {
            frmUploader frm = new frmUploader(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);

            //FolderNode node = tvFolders.SelectedNode as FolderNode;
            //IFileManagement f = session as IFileManagement;
            //f.ChunkSize = 262144;
            //f.OpenUploadWindow(true, node.MetaData);

            //searchFiles("", node.MetaData.name, node.MetaData.value, 0, long.Parse((string)cboTxtSize.SelectedItem));
        }

        private void lvFiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            
        }

        private void lvFiles_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                unDeleteToolStripMenuItem.Enabled = false;
                deleteToolStripMenuItem.Enabled = false;

                if (lvFiles.SelectedIndices.Count > 1)  //
                {
                    renameToolStripMenuItem.Enabled = false;
                    this.filePropertiesToolStripMenuItem.Enabled = false;

                    getDownloadUrlToolStripMenuItem.Enabled = false;
                    openInBrowserToolStripMenuItem.Enabled = false;

                    foreach (ListViewItem item in lvFiles.SelectedItems)
                    {
                        bool isdeleted = item.SubItems[3].Text.Equals("True", StringComparison.CurrentCultureIgnoreCase);
                        bool iscomplete = item.SubItems[4].Text.Equals("True", StringComparison.CurrentCultureIgnoreCase);

                        if (isdeleted)
                        {
                            unDeleteToolStripMenuItem.Enabled = true;
                        }
                        else
                        {
                            deleteToolStripMenuItem.Enabled = true;
                        }
                    }

                }
                else
                {
                    bool isdeleted = lvFiles.SelectedItems[0].SubItems[3].Text.Equals("True", StringComparison.CurrentCultureIgnoreCase);
                    bool iscomplete = lvFiles.SelectedItems[0].SubItems[4].Text.Equals("True", StringComparison.CurrentCultureIgnoreCase);

                    deleteToolStripMenuItem.Enabled = !isdeleted;
                    unDeleteToolStripMenuItem.Enabled = isdeleted;
                    openInBrowserToolStripMenuItem.Enabled = true;//!isdeleted && iscomplete;
                    getDownloadUrlToolStripMenuItem.Enabled = !isdeleted && iscomplete;

                    this.filePropertiesToolStripMenuItem.Enabled = true;
                }

                if (tvFolders.SelectedNode != null && ((FolderNode)tvFolders.SelectedNode).MetaData.metaDataID > 0)
                {
                    this.removeFromFolderToolStripMenuItem.Enabled = true;
                }
                else
                {
                    this.removeFromFolderToolStripMenuItem.Enabled = false;
                }

                contextMenuLv.Show(lvFiles, e.Location);
            }
            else
            {
                lastclick = "Files";
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IFileManagement f = session as IFileManagement;
            foreach (ListViewItem item in lvFiles.SelectedItems)
            {
                bool isdeleted = item.SubItems[3].Text.Equals("True", StringComparison.CurrentCultureIgnoreCase);
                if (!isdeleted)
                {
                    int id = int.Parse(item.SubItems[1].Text);
                    IStoredFile file = f.StoredFileInstance(id);
                    writeStatus(string.Format("Deleting {0}...", item.Text));
                    IStoredFileExecResult result = file.Delete();
                    if (result.Status != Diomede.SDK.Enums.ExecutionResults.Success)
                    {
                        MessageBox.Show(this, result.Message, "Delete Error.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                
            }
            writeStatus("Delete complete.");
            btnShowFiles_Click(null, null);
        }

        private void renameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ListViewItem item = lvFiles.SelectedItems[0];
            InputBox dlg = new InputBox("Rename " + item.Text, "Enter new name for " + item.Text, item.Text, null);
            if ( dlg.ShowDialog(this) == DialogResult.OK)
            {
                IFileManagement f = session as IFileManagement;
                int id = int.Parse(item.SubItems[1].Text);
                IStoredFile file = f.StoredFileInstance(id);
                IStoredFileExecResult result = file.Rename(dlg.InputString);
                if (result.Status != Diomede.SDK.Enums.ExecutionResults.Success)
                {
                    MessageBox.Show(this,  result.Message);
                }
                else
                {
                    // like the user cares.. MessageBox.Show(this,"Rename successful.");
                    btnShowFiles_Click(null, null);
                }
            }
            dlg.Dispose();
            
        }

        private void getDownloadUrlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ListViewItem item = lvFiles.SelectedItems[0];
            if (item.SubItems[4].Text == "True")
            {
                IFileManagement f = session as IFileManagement;
                int id = int.Parse(item.SubItems[1].Text);
                IStoredFile file = f.StoredFileInstance(id);
                string url = file.GetDownloadUrl(null, null, null, "");
                if (!string.IsNullOrEmpty(url))
                    Clipboard.SetText(url);
                MessageBox.Show(this, "The URL has been copied to your clipboard.\r\n" + url,"Get Download URL");
            }
            else
            {
                MessageBox.Show(this, "Cannot download incomplete files.", "Get Download URL");
            }
        }

        private void openInBrowserToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ListViewItem item = lvFiles.SelectedItems[0];

            IFileManagement f = session as IFileManagement;
            int id = int.Parse(item.SubItems[1].Text);
            IStoredFile file = f.StoredFileInstance(id);
            string url = file.GetDownloadUrl(3, null, null, "www.google.com");
            
            frmBrowser frm = new frmBrowser(url);
            frm.MdiParent = this.MdiParent;
            frm.Show();
        }

        private void btnUserInfo_Click(object sender, EventArgs e)
        {
            frmUserInformation frm = new frmUserInformation(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }

        private void frmExplorer_Load(object sender, EventArgs e)
        {
            this.Icon = Diomede.Explorer.Properties.Resources.diofolder;
            this.cboTxtSize.SelectedIndex = 2;
            this.WindowState = FormWindowState.Maximized;
            Timer tm = new Timer();
            tm.Interval = 500;
            tm.Tick += new EventHandler(tm_Tick);
            tm.Start();
            
        }

        void tm_Tick(object sender, EventArgs e)
        {
            (sender as Timer).Stop();
            tsBtnLogin_Click(null, null);
            lvFiles.Focus();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            tvFolders.SelectedNode = null;
            searchFiles(txtSearchQ.Text,null,null, 0, long.Parse((string)cboTxtSize.SelectedItem));
        }

        private void txtSearchQ_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                tvFolders.SelectedNode = null;
                searchFiles(txtSearchQ.Text, null, null, 0, long.Parse((string)cboTxtSize.SelectedItem));
            }
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            if (tvFolders.SelectedNode == null || ((FolderNode)tvFolders.SelectedNode).MetaData.name == "root-folder")
            {
                searchFiles(txtSearchQ.Text, null, null, pageInfo.NextOffset, pageInfo.PageSize);
            }
            else
            {
                FolderNode node = tvFolders.SelectedNode as FolderNode;
                searchFiles(txtSearchQ.Text, node.MetaData.name, node.MetaData.value, pageInfo.NextOffset, pageInfo.PageSize);
            }
        }

        private void btnPrev_Click(object sender, EventArgs e)
        {
            if (tvFolders.SelectedNode == null || ((FolderNode)tvFolders.SelectedNode).MetaData.name == "root-folder")
            {
                searchFiles(txtSearchQ.Text, null, null, pageInfo.PreviousOffset, pageInfo.PageSize);
            }
            else
            {
                FolderNode node = tvFolders.SelectedNode as FolderNode;
                searchFiles(txtSearchQ.Text, node.MetaData.name, node.MetaData.value, pageInfo.PreviousOffset, pageInfo.PageSize);
            }
        }

        private void btnMyEmails_Click(object sender, EventArgs e)
        {
            frmEmails frm = new frmEmails(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
            
        }

        private void unDeleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IFileManagement f = session as IFileManagement;
            foreach (ListViewItem item in lvFiles.SelectedItems)
            {
                bool isdeleted = item.SubItems[3].Text.Equals("True", StringComparison.CurrentCultureIgnoreCase);
                if (isdeleted)
                {
                    int id = int.Parse(item.SubItems[1].Text);
                    IStoredFile file = f.StoredFileInstance(id);
                    writeStatus(string.Format("Undeleting {0}...", item.Text));
                    IStoredFileExecResult result = file.Undelete();
                    if (result.Status != Diomede.SDK.Enums.ExecutionResults.Success)
                    {
                        MessageBox.Show(this, result.Message, "Undelete Error.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

            }
            writeStatus("Undelete complete.");
            btnShowFiles_Click(null, null);

        }

        private void btnChangePassword_Click(object sender, EventArgs e)
        {
            frmChangePassword frm = new frmChangePassword(session);
            frm.ShowDialog();
            frm.Dispose();
        }

        private void btnFilesSummary_Click(object sender, EventArgs e)
        {
            IFileManagement f = session as IFileManagement;
            bool? includeDeleted = false;
            if (chkShowDeleted.Checked) includeDeleted = null;
            bool? completeOnly = true;
            if (chkIncompleteFiles.Checked) completeOnly = null;

            ISearchFilesSummaryResult result = f.SearchFilesSummary(null, string.Empty, string.Empty, string.Empty, null, null, null, null, includeDeleted, completeOnly, null, null);
            if (result.Status == Diomede.SDK.Enums.ExecutionResults.Success)
            {
                frmSummaryInfo frm = new frmSummaryInfo(result.FileTotalInfo, "File Storage Summary");
                frm.StartPosition = FormStartPosition.CenterParent;
                frm.ShowDialog(this);
            }
            else
            {
                writeStatus(result.Message);
            }
        }

        private void btnMergeActivityLogs_Click(object sender, EventArgs e)
        {
            frmFileTotalLogsSearch frm = new frmFileTotalLogsSearch(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }

        private void btnMyProducts_Click(object sender, EventArgs e)
        {
            frmUserProduct frm = new frmUserProduct(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);

        }

        private void btnDeleteAccount_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(this, "Do you really want to delete this account?", "Delete account", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                IAccountManagement account = session as IAccountManagement;
                account.Delete();
                MessageBox.Show("User Account has been successfuly deleted.");
                tsBtnLogin_Click(null, null);
            }
        }

        private void btnUploadActivityLogs_Click(object sender, EventArgs e)
        {
            frmUploadLogs frm = new frmUploadLogs(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }

        private void btnDownloadActivityLog_Click(object sender, EventArgs e)
        {
            frmDownloadLogs frm = new frmDownloadLogs(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }

        private void btnLoginActivityLogs_Click(object sender, EventArgs e)
        {
            frmLoginLogs frm = new frmLoginLogs(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }

        private void btnMyContracts_Click(object sender, EventArgs e)
        {
            frmUserContracts frm = new frmUserContracts(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            frmInvoiceLogs frm = new frmInvoiceLogs(session);
            frm.ShowDialog(this);
        }

        private MetaData FolderMetaListSearch(string type, string search, List<MetaData> md)
        {
                MetaData metadatasearch = md.Find(delegate(MetaData mds)
                {
                    if (type=="startswith")
                        return mds.value.StartsWith(search);
                    else if (type=="exact")
                        return mds.value == search;
                    else
                    return false;
                }
                );
                if (metadatasearch != null) return metadatasearch;
                else
                    return null;

        }

        void LoadFolders(int? metaId)
        {
            this.Cursor = Cursors.WaitCursor;
            tvFolders.Nodes.Clear();

            List<MetaData> md = fileManager.GetAllFolders();
            FolderNode root = new FolderNode()
            {
                MetaData = new MetaData() { name = "root-folder", value = "/" },
                Text = "(All files)",
                ImageIndex = 1,
                SelectedImageIndex = 2,
                Name = "/"
            };

            tvFolders.Nodes.Add(root);
            if (md != null)
            {
                if (md.Count > 0)
                {
                    // Diomede folder file system check and fix

                    // is there any // folders?
                    MetaData mds = FolderMetaListSearch("startswith", "//", md);
                    if (mds != null)
                    {
                        // is there a // root?
                        MetaData mdsroot = FolderMetaListSearch("exact", "//", md);
                        if (mdsroot == null)
                        {
                            // create one... 
                            // create new // metadata
                            IFileManagement f = session as IFileManagement;

                            ICreateMetaDataExecResult result = f.CreateMetaData("SourceRelativePath", "//");
                            if (result.Status == Diomede.SDK.Enums.ExecutionResults.Failed)
                            {
                                MessageBox.Show(this, result.Message, "Error");
                                return;
                            }
                            mdsroot = new MetaData();
                            mdsroot.metaDataID = result.MetaDataID;

                        }
                        FolderNode newtop = null;
                        newtop = CreateNode(newtop, "//");
                        newtop.MetaData.metaDataID = mdsroot.metaDataID;
                        newtop.Name = "//";
                        newtop.MetaData.name = "SourceRelativePath";
                        newtop.MetaData.value = "//";
                        tvFolders.Nodes.Add(newtop);
                    }

                    foreach (var item in md)
                    {
                        string sval = item.value;
                        if (sval.StartsWith(@"//"))
                            sval = sval.Substring(2);

                        string[] nstrs = sval.Split(@"/".ToCharArray());

                        if (nstrs.Length == 1)
                            if (nstrs[0] == "") nstrs[0] = "//";

                        FolderNode node = null;

                        for (int i = 0; i < nstrs.Length; i++)
                        {
                            string s = nstrs[i];

                            if (node == null)
                            {
                                if (s != "//" && tvFolders.Nodes.Count > 1 && tvFolders.Nodes[1].Nodes.ContainsKey(s))
                                {
                                    node = tvFolders.Nodes[1].Nodes[s] as FolderNode;
                                }
                                else
                                {
                                    node = CreateNode(node, s);
                                    if (i == nstrs.Length - 1)
                                    {
                                        node.MetaData.metaDataID = item.metaDataID;
                                    }

                                    if (s != "//" && item.value.StartsWith("//")) tvFolders.Nodes[1].Nodes.Add(node);
                                    else if (s != "//" && !item.value.StartsWith("//")) tvFolders.Nodes.Add(node);
                                    //if (s == "//") if (tvFolders.Nodes.Count < 1) tvFolders.Nodes.Add(node);
                                    //else if (tvFolders.Nodes.Count == 1 && !s.StartsWith("//") && item.value.StartsWith("//"))
                                    //{


                                    //// create new // metadata
                                    //IFileManagement f = session as IFileManagement;

                                    //ICreateMetaDataExecResult result = f.CreateMetaData("SourceRelativePath", "//");
                                    //if (result.Status == Diomede.SDK.Enums.ExecutionResults.Failed)
                                    //{
                                    //    MessageBox.Show(this, result.Message, "Error");
                                    //    return;
                                    //}
                                    //FolderNode newtop = null;
                                    //newtop = CreateNode(newtop, "//");
                                    //newtop.MetaData.metaDataID = result.MetaDataID;
                                    //newtop.Name = "//";
                                    //newtop.MetaData.name = "//";
                                    //newtop.MetaData.value = "//";

                                    //tvFolders.Nodes.Add(newtop);
                                    //tvFolders.Nodes[1].Nodes.Add(node);
                                    //}
                                    //else tvFolders.Nodes[1].Nodes.Add(node);
                                    //tvFolders.Nodes.Add(node);
                                }
                            }
                            else
                            {
                                node = CreateNode(node, s);
                                if (i == nstrs.Length - 1)
                                {
                                    node.MetaData.metaDataID = item.metaDataID;
                                }

                                if (item.metaDataID == metaId.GetValueOrDefault(0))
                                {
                                    tvFolders.SelectedNode = node;
                                }
                            }
                        }
                        if (tvFolders.SelectedNode == null)
                            tvFolders.SelectedNode = tvFolders.Nodes[0];

                    }

                }
                tvFolders.ExpandAll();
                this.Cursor = Cursors.Arrow;
            }
        } // end checking for null md object

        FolderNode CreateNode(FolderNode parent, string text)
        {
            bool hasParent = parent != null;
            if (hasParent && parent.Nodes.ContainsKey(text))
            {
                return (FolderNode)parent.Nodes[text];
            }
            else
            {
                FolderNode node = new FolderNode() { 
                    MetaData = new MetaData() { Session = session, name = "SourceRelativePath", value = hasParent ? string.Format("{0}/{1}", parent.MetaData.value,text) : text }, 
                    Text = text,
                    ImageIndex = 1,
                    SelectedImageIndex = 2,
                    Name = text
                };
                if (!node.MetaData.value.StartsWith("//"))
                {
                    node.MetaData.value = "//" + node.MetaData.value;
                }

                if (hasParent)
                    parent.Nodes.Add(node);

                return node;
            }
        }

        private void tvFolders_AfterSelect(object sender, TreeViewEventArgs e)
        {
            FolderNode node = e.Node as FolderNode;
            if (node.MetaData.name == "root-folder")
            {
                searchFiles("", null, null, 0, long.Parse((string)cboTxtSize.SelectedItem));
            }
            else
            {
                string v = node.MetaData.value;
                if (!v.StartsWith(@"//"))
                    v = "//" + v;

                searchFiles("", node.MetaData.name, v, 0, long.Parse((string)cboTxtSize.SelectedItem));
            }
        }

        private void copyToFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmMetaData frm = new frmMetaData(session);
            if (frm.ShowDialog(this) == DialogResult.OK)
            {
                IFileManagement f = session as IFileManagement;
                foreach (ListViewItem item in lvFiles.SelectedItems)
                {
                    int id = int.Parse(item.SubItems[1].Text);
                    IStoredFile file = f.StoredFileInstance(id);
                    file.AddMetaData(frm.SelectedMetaDataID);
                }
                LoadFolders(frm.SelectedMetaDataID);
            }
        }

        private void copyToNewFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            InputBox box = new InputBox("Folder", "Input Folder name", "New Folder","Folder will be created under root");
            if (box.ShowDialog(this) == DialogResult.OK)
            {
                IFileManagement f = session as IFileManagement;
                int? mId = null;
                foreach (ListViewItem item in lvFiles.SelectedItems)
                {
                    int id = int.Parse(item.SubItems[1].Text);
                    IStoredFile file = f.StoredFileInstance(id);
                    if (mId.HasValue)
                    {
                        file.AddMetaData(mId.Value);
                    }
                    else
                    {
                        IAddMetaDataExecResult m = file.AddMetaData("SourceRelativePath", box.InputString);
                        mId = m.MetaDataID;
                    }
                }

                LoadFolders(mId);
            }
        }

        private void tvFolders_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                tvFolders.SelectedNode = e.Node;
                contextMenuTv.Show((Control)sender, e.Location);
            }
            else
            {
                lastclick = "Folders";
            }
        }

        private void renameToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            FolderNode node = tvFolders.SelectedNode as FolderNode;
            if (node.Nodes.Count > 0)
            {
                if (MessageBox.Show(this, "The selected folder to rename has a sub-folder, if you continue all sub-folders will remain blah blah..., Do you want to continue rename?", "Rename", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return;
                }
            }

            InputBox box = new InputBox("Rename Folder", "Enter new folder name", node.MetaData.value, null);
            if (box.ShowDialog(this) == DialogResult.OK)
            {
                node.MetaData.Update("SourceRelativePath", box.InputString);
                LoadFolders(node.MetaData.metaDataID);
            }
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            FolderNode node = tvFolders.SelectedNode as FolderNode;
            if (node.Nodes.Count > 0)
            {
                if (MessageBox.Show(this, "The selected folder to delete has a sub-folder, if you continue all sub-folders will remain blah blah..., Do you want to continue rename?", "Rename", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return;
                }
            }

            node.MetaData.DeleteAllInstances();
            LoadFolders(null);
        }

        private void removeFromFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderNode node = tvFolders.SelectedNode as FolderNode;

            IFileManagement f = session as IFileManagement;
            foreach (ListViewItem item in lvFiles.SelectedItems)
            {
                    int id = int.Parse(item.SubItems[1].Text);
                    IStoredFile file = f.StoredFileInstance(id);

                    IRemoveMetaDataExecResult result = file.RemoveMetaData(node.MetaData.metaDataID);
                    if (result.Status != Diomede.SDK.Enums.ExecutionResults.Success)
                    {
                        MessageBox.Show(this, result.Message, "Metadata remove Error.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

            }
            LoadFolders(node.MetaData.metaDataID);
        }

        private void uploadFilesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderNode node = tvFolders.SelectedNode as FolderNode;
            //IFileManagement f = session as IFileManagement;
            //f.ChunkSize = 262144;
            //f.OpenUploadWindow(true, node.MetaData);
            frmUploader frm = new frmUploader(session, node);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);

            searchFiles("", node.MetaData.name, node.MetaData.value, 0, long.Parse((string)cboTxtSize.SelectedItem));

        }

        private void createNewFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderNode node = tvFolders.SelectedNode as FolderNode;

            string newfolder = node.MetaData.value;
            if (newfolder == "/") newfolder = "//";
            InputBox box = new InputBox("Create Folder", "Enter folder name", "New Folder", "Folder will be created under: " + newfolder);
            if (box.ShowDialog(this) == DialogResult.OK)
            {
                IFileManagement f = session as IFileManagement;
                if (!newfolder.EndsWith("/")) newfolder += "/";
                ICreateMetaDataExecResult result = f.CreateMetaData("SourceRelativePath", newfolder + box.InputString);
                if (result.Status == Diomede.SDK.Enums.ExecutionResults.Failed)
                {
                    MessageBox.Show(this, result.Message, "Error");
                    return;
                }
                LoadFolders(result.MetaDataID);
            }

        }

        private void filePropertiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmMetaData frm = new frmMetaData(session);
            int id = int.Parse(lvFiles.SelectedItems[0].SubItems[1].Text);
            frm.FileID = id;
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }

        private void replicationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmFileReplication frm = new frmFileReplication(session);
            int id = int.Parse(lvFiles.SelectedItems[0].SubItems[1].Text);
            frm.FileID = id;
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
        }


        private void toolStripButtonUpload_Click(object sender, EventArgs e)
        {
            frmUploader frm = new frmUploader(session);
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.ShowDialog(this);
            if (frm.DialogResult == DialogResult.OK) toolStripButtonRefresh_Click(null, null);
        }

        private void toolStripButtonNewFolder_Click(object sender, EventArgs e)
        {
            this.createNewFolderToolStripMenuItem_Click(sender, e);
        }

        private void toolStripButtonDelete_Click(object sender, EventArgs e)
        {
            if (lastclick == "Folders")
            {
                deleteToolStripMenuItem1_Click(sender, e);
            }
            else if (lastclick == "Files")
            {
                deleteToolStripMenuItem_Click(sender, e);
            }
        }

        private void toolStripButtonRename_Click(object sender, EventArgs e)
        {
            if (lastclick == "Folders")
            {
                renameToolStripMenuItem1_Click(sender, e);
            }
            else if (lastclick == "Files")
            {
                renameToolStripMenuItem_Click(sender, e);
            }
        }

        private void toolStripButtonRefresh_Click(object sender, EventArgs e)
        {
            LoadFolders(null);
            btnShowFiles_Click(sender, e);
        }

        private void cboTxtSize_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (splitContainerMain.Panel1.Enabled)
                btnShowFiles_Click(sender, e);
        }

        private void chkShowDeleted_CheckedChanged(object sender, EventArgs e)
        {
            toolStripButtonRefresh_Click(sender, e);
        }

        private void chkIncompleteFiles_CheckedChanged(object sender, EventArgs e)
        {
            toolStripButtonRefresh_Click(sender, e);
        }

        private void lvFiles_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (lvFiles.SelectedItems.Count > 0) // verify something is clicked on...
            {
                openInBrowserToolStripMenuItem_Click(sender, e);
            }
        }



    }

    public class PageInfo
    {
        public PageInfo() { }
        public PageInfo(long total, long offset, int pageSize) 
        {
            TotalResults = total;
            CurrentOffset = offset;
            PageSize = pageSize;
            computeValues();
        }

        void computeValues()
        {
            NextOffset = CurrentOffset + PageSize;
            PreviousOffset = CurrentOffset - PageSize;

            TotalPage = ((int)TotalResults / PageSize);
            if ((TotalPage * PageSize) < TotalResults)
                TotalPage += 1;

            CurrentPage = ((int)CurrentOffset / PageSize) + 1;
        }

        public PageInfo NextPage()
        {
            return new PageInfo(TotalPage, NextOffset, PageSize);
        }

        public PageInfo PreviousPage()
        {
            return new PageInfo(TotalPage, PreviousOffset, PageSize);
        }

        public int CurrentPage { get; set; }
        public int TotalPage { get; set; }
        public long CurrentOffset { get; set; }
        public long NextOffset { get; set; }
        public long PreviousOffset { get; set; }
        public long TotalResults { get; set; }
        public int PageSize { get; set; }
    }
    public class StringManip
    {
        static public string EncodeTo64(string toEncode)
        {
            byte[] toEncodeAsBytes
                  = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
            string returnValue
                  = System.Convert.ToBase64String(toEncodeAsBytes);
            return returnValue;

        }

        static public string DecodeFrom64(string encodedData)
        {
            byte[] encodedDataAsBytes
                = System.Convert.FromBase64String(encodedData);
            string returnValue =
               System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
            return returnValue;
        }

    }
}
